# Create your views here.
import feedparser, datetime, operator, pytz, sha, random
from BeautifulSoup import BeautifulSoup
from django.shortcuts import get_list_or_404, get_object_or_404, render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect, Http404, HttpResponse
from chicago.models import  *
from repsheet.forms import *
from geopy import geocoders  
from django.conf import settings
from django.contrib.gis.geos import *
from django.template.defaultfilters import slugify
from django.core.urlresolvers import reverse
from django.views.decorators.cache import cache_page
from django.contrib.gis.maps.google import GoogleMap
from django.utils import feedgenerator
from django.core.mail import send_mail

TZ = pytz.timezone(settings.TIME_ZONE)
FEED_SLICE = settings.REPSHEET_FEED_SLICE
SITE = Site.objects.get_current()

def lookup(request, template_name="lookup.html"): 
    """
    Get the lat/long for an address and redirect to the detail view.
    """
    
    location=request.GET.get('location',False)
    place = ''
    not_found = False

    if location:
        form = LookupForm(initial={'location':location})
        g = geocoders.Google(settings.GOOGLE_MAPS_API_KEY)
        places = list(g.geocode(
                        '%s Chicago, IL' % location.encode('utf-8'), 
                        exactly_one=False))
        try:
            place = places[0][0]
        except IndexError:
            pass

        if place:
            form = LookupForm({'location':place})
            if form.is_valid():
                return HttpResponseRedirect(
                           reverse(
                            'repsheet_detail',
                            kwargs={'slug':slugify(place)}))
        else:
            not_found = True

    else:
        form = LookupForm(initial={'location':place})
    
    return render_to_response( 
            
            template_name, 
            { 
                'form':form,
                'not_found':not_found,
                'gmaps_key':settings.GOOGLE_MAPS_API_KEY,
            }, 
            context_instance=RequestContext(request),
           )

# ineffective if caching all with middleware
#@cache_page(60 * 60)
def detail(request, slug, template_name="detail.html", rss=False):
    """
    Take a location/point and display the related information.
    """
    place = None
    location = slug.replace('-',' ')
    g = geocoders.Google(settings.GOOGLE_MAPS_API_KEY)
    try:
        place, (lat, lng) = g.geocode(location.encode('utf-8'))
        pnt = Point(lng,lat, srid=4326)
    except ValueError:
        raise Http404, 'Sorry couldn\'t find it.'

    # we got a place, do something!
    form = LookupForm(initial={'location':place})
    kml_prefix = 'http://%s' % SITE.domain
    news = []
    ward = ward_map = house = house_map = None
    senate = senate_map = congress = congress_map = None

    try:
        ward = Ward.objects.filter(area__contains=pnt)[0]
        ward_map = GoogleMap(
                    dom_id="ward_map",
                    markers=[pnt],
                    #polygons=[wards[0].area],
                    kml_urls=[
                        kml_prefix+reverse(
                            'chicago_wards_kml', 
                            args=[ward.id])],)
    except IndexError:
        pass

    try: 
        for feedmap in ward.rep.feeds.all():
            news += feedmap.feed.feeditem_set.filter(ignore=False)[:FEED_SLICE]
    except AttributeError:
        pass

    try:
        house = House.objects.filter(area__contains=pnt)[0]
        house_map = GoogleMap(
                        dom_id = 'house_map',
                        markers=[pnt],
                        #polygons=[houses[0].area],
                        kml_urls=[
                            kml_prefix+reverse(
                                'chicago_house_kml', 
                                args=[house.id])],)
    except IndexError:
        pass

    try:
        for feedmap in house.rep.feeds.all():
            news += feedmap.feed.feeditem_set.filter(ignore=False)[:FEED_SLICE]
    except AttributeError:
        pass

    try:
        senate = Senate.objects.filter(area__contains=pnt)[0]
        senate_map = GoogleMap(
                        dom_id = 'senate_map',
                        markers=[pnt],
                        #polygons=[houses[0].area],
                        kml_urls=[
                            kml_prefix+reverse(
                                'chicago_senate_kml', 
                                args=[senate.id])],)
    except IndexError:
        pass

    try:
        for feedmap in senate.rep.feeds.all():
            news += feedmap.feed.feeditem_set.filter(ignore=False)[:FEED_SLICE]
    except AttributeError:
        pass

    try:
        congress = Congress.objects.filter(area__contains=pnt)[0]
        congress_map = GoogleMap(
                        dom_id = 'congress_map',
                        markers=[pnt],
                        #polygons=[houses[0].area],
                        kml_urls=[
                            kml_prefix+reverse(
                                'chicago_congress_kml', 
                                args=[congress.id])],)
    except IndexError:
        pass

    try:
        for feedmap in congress.rep.feeds.all():
            news += feedmap.feed.feeditem_set.filter(ignore=False)[:FEED_SLICE]
    except AttributeError:
        pass

    # sort according to date, got from IRC #python.
    news.sort(key=operator.attrgetter('date_modified'),reverse=True)
    for n in news:
        # timestamp manipulation to TZ
        d = n.date_modified.replace(tzinfo=pytz.utc)
        n.date_modified = d.astimezone(TZ)

    # mushing an rss feed in 
    if rss:

        f = feedgenerator.Rss201rev2Feed(
            title=u"RepSheet for %s" % place,
            link=u"http://repsheet.com/%s/" % slug,
            description=u"Look up your elected representatives.",
            language=u"en")

        for n in news:
            f.add_item(
                title = n.title,
                link = n.link,
                description = n.summary,
                date_modified = n.date_modified)

        return HttpResponse(f.writeString('UTF-8'))

    else:

        return render_to_response(
                template_name, 
                {
                    'form':form,
                    'place':place,
                    'slug':slug,
                    'ward':ward,
                    'ward_map':ward_map,
                    'house':house,
                    'house_map':house_map,
                    'senate':senate,
                    'senate_map':senate_map,
                    'congress':congress,
                    'congress_map':congress_map,
                    'news':news,
                    'gmaps_key':settings.GOOGLE_MAPS_API_KEY,
                }, 
                context_instance=RequestContext(request),
               )

def subscribe(request, slug, template_name="subscribe.html", ):

    place = point = None
    location = slug.replace('-',' ')
    g = geocoders.Google(settings.GOOGLE_MAPS_API_KEY)
    try:
        place, (lat, lng) = g.geocode(location)
        point = Point(lng,lat, srid=4326)
    except ValueError:
        raise Http404, 'Sorry couldn\'t find it.'

    if request.POST:
        ward = senate = house = congress = None
        reps = []

        form = SubForm(request.POST)
        if form.is_valid():
            try:
                ward = Ward.objects.filter(area__contains=point)[0]
            except IndexError:
                pass
            try:
                congress = Congress.objects.filter(area__contains=point)[0]
            except IndexError:
                pass
            try:
                senate = Senate.objects.filter(area__contains=point)[0]
            except IndexError:
                pass
            try:
                house = House.objects.filter(area__contains=point)[0]
            except IndexError:
                pass

            email = form.cleaned_data['email']
            salt = sha.new(str(random.random())).hexdigest()[:5]
            key = sha.new(salt+email).hexdigest()

            sub = Subscription(
                    email = email,
                    ward = ward,
                    house = house,
                    congress = congress,
                    senate = senate,
                    point = point,
                    place = place,
                    confirm_key = key,
                    feed = reverse(
                                'repsheet_detail_rss',
                                kwargs={'slug':slug,'rss':'rss'}))
            sub.save()

            subject = render_to_string(
                        'subscribe_confirm_subject.txt')
            subject = ''.join(subject.splitlines())
            message = render_to_string(
                        'subscribe_confirm_email.txt',
                        {'confirm_url':reverse(
                                'repsheet_subscribe_complete',args=[key]),
                         'site':SITE})
            send_mail( subject,
                       message,
                       settings.DEFAULT_FROM_EMAIL,
                       [sub.email])

            return HttpResponseRedirect(reverse('repsheet_subscribe_confirm'))
    else:
        form = SubForm(
                initial={
                    'feed':reverse('repsheet_detail_rss',
                                   kwargs={'slug':slug, 'rss':'rss'})})

    return render_to_response(
            template_name, 
            { 'form':form, 'place':place , 'slug':slug},
            context_instance=RequestContext(request),)


def subscribe_complete(request, confirm_key,
        template_name="subscribe_complete.html"):

    sub = Subscription.objects.confirm_sub(confirm_key)
                
    return render_to_response(
            template_name, 
            { 'sub' : sub},
            context_instance=RequestContext(request),)

def subscribe_remove(request, confirm_key, template_name="subscribe_remove.html", ):

    sub = get_object_or_404(Subscription, confirm_key=confirm_key)
    already_removed = False

    if not sub.remove:
        sub.remove = True
        sub.save()
    else:
        already_removed = True

    return render_to_response(
            template_name, 
            { 'sub' : sub, 'already_removed':already_removed },
            context_instance=RequestContext(request),)

    

